//
//  HTTPHelper.m
//  Perking
//
//  Created by longmin on 16/7/12.
//  Copyright © 2016年 tim. All rights reserved.
//

#import "HTTPHelper.h"
#import "NSString+Extention.h"
#import<CommonCrypto/CommonDigest.h>

@implementation HTTPHelper

static HTTPHelper * instance;

+ (id)allocWithZone:(struct _NSZone *)zone
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [super allocWithZone:zone];
        //增加这几行代码；
        AFSecurityPolicy *securityPolicy = [[AFSecurityPolicy alloc] init];
        [securityPolicy setAllowInvalidCertificates:YES];
        instance.responseSerializer = [AFHTTPResponseSerializer serializer];
        instance.requestSerializer = [AFHTTPRequestSerializer serializer];
        //这里进行设置；
        [instance setSecurityPolicy:securityPolicy];
        instance.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/html",@"text/json",@"text/plain",@"text/javascript", nil];
    });
    
    return instance;
}

-(NSURLSessionDataTask *)get:(NSString *)URLString
                      params:(NSDictionary *)params
                    useToken:(BOOL)useToken
                    progress:(void (^)(NSProgress * progress))downloadProgress
                     success:(void (^)(NSURLSessionDataTask *task, NSDictionary *result, HTTPStatus *status))success
                     failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
{
    
    NSURLSessionDataTask *sessionDataTask = [self GET:URLString
                                           parameters:[self setHeader:useToken AddTimeWithDict:params]
                                             progress:downloadProgress
                                              success:[self formatSuccess:success]
                                              failure:[self formatFailure:failure]];
    return sessionDataTask;
}

-(NSURLSessionDataTask *)get:(NSString *)URLString
                      params:(NSDictionary *)params
                    useToken:(BOOL)useToken
                    showText:(NSString *)showText
                     success:(void (^)(NSURLSessionDataTask * task, NSDictionary *result, HTTPStatus *status))success
                     failure:(void (^)(NSURLSessionDataTask * task, NSError * error))failure
{
    
    [self showText:showText];
    
    NSURLSessionDataTask *sessionDataTask = [self get:URLString
                                               params:params
                                             useToken:useToken
                                             progress:nil
                                              success:[self addWaitText:showText success:success]
                                              failure:[self addWaitText:showText failure:failure]];
    return sessionDataTask;
}

-(NSURLSessionDataTask *)post:(NSString *)URLString
                       params:(NSDictionary *)params
                     useToken:(BOOL)useToken
                     progress:(void (^)(NSProgress * progress))uploadProgress
                      success:(void (^)(NSURLSessionDataTask * task, NSDictionary *result, HTTPStatus *status))success
                      failure:(void (^)(NSURLSessionDataTask * task, NSError * error))failure
{

    NSURLSessionDataTask *sessionDataTask = [self POST:URLString
                                            parameters:[self setHeader:useToken AddTimeWithDict:params]
                                              progress:uploadProgress
                                               success:[self formatSuccess:success]
                                               failure:[self formatFailure:failure]];
    return sessionDataTask;
}

-(NSURLSessionDataTask *)post:(NSString *)URLString
                       params:(NSDictionary *)params
                     useToken:(BOOL)useToken
                     showText:(NSString *)showText
                      success:(void (^)(NSURLSessionDataTask * task, NSDictionary *result, HTTPStatus *status))success
                      failure:(void (^)(NSURLSessionDataTask * task, NSError * error))failure
{
    
    [self showText:showText];

    NSURLSessionDataTask *sessionDataTask = [self post:URLString
                                                params:params
                                              useToken:useToken
                                              progress:nil
                                               success:[self addWaitText:showText success:success]
                                               failure:[self addWaitText:showText failure:failure]];
    return sessionDataTask;
}

-(NSURLSessionDataTask *)post:(NSString *)URLString
                       params:(NSDictionary *)params
                     useToken:(BOOL)useToken
    constructingBodyWithBlock:(void (^)(id<AFMultipartFormData> formData))block
                     progress:(void (^)(NSProgress * progress))uploadProgress
                      success:(void (^)(NSURLSessionDataTask * task, NSDictionary *result, HTTPStatus *status))success
                      failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
{
    
    NSURLSessionDataTask *sessionDataTask = [self POST:URLString
                                            parameters:[self setHeader:useToken AddTimeWithDict:params]
                             constructingBodyWithBlock:block
                                              progress:uploadProgress
                                               success:[self formatSuccess:success]
                                               failure:[self formatFailure:failure]];
    return sessionDataTask;
}

- (void)syncGet:(NSString *)URLString
         params:(NSDictionary *)params
       useToken:(BOOL)useToken
        success:(void (^)(NSURLSessionDataTask *task,NSDictionary *result, HTTPStatus *status))success
        failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
{
    [self syncRequest:URLString method:@"GET" params:params useToken:useToken success:success failure:failure];
}

- (void)syncPost:(NSString *)URLString
          params:(NSDictionary *)params
        useToken:(BOOL)useToken
         success:(void (^)(NSURLSessionDataTask *task,NSDictionary *result, HTTPStatus *status))success
         failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
{

    [self syncRequest:URLString method:@"POST" params:params useToken:useToken success:success failure:failure];
}

- (void)syncRequest:(NSString *)URLString
             method:(NSString *)method
             params:(NSDictionary *)params
           useToken:(BOOL)useToken
            success:(void (^)(NSURLSessionDataTask *task,NSDictionary *result, HTTPStatus *status))success
            failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
{
    
    NSDictionary *dict = [self setHeader:useToken AddTimeWithDict:params];

    //创建请求
    NSMutableURLRequest *newRequest = [self.requestSerializer requestWithMethod:method URLString:URLString parameters:dict error:nil];
    
    //发送同步请求
    dispatch_semaphore_t disp = dispatch_semaphore_create(0);
    NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:newRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        //请求失败,超时处理
        if (error) {
            [self formatFailure:failure](dataTask,error);
            return;
        }
        //处理请求结果
        NSDictionary *JSON = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
        
        [self formatSuccess:success](dataTask,JSON);
        
        dispatch_semaphore_signal(disp);
    }];
    [dataTask resume];
    dispatch_semaphore_wait(disp, DISPATCH_TIME_FOREVER);
}


+ (instancetype)sharedHTTPHelper
{
    if (instance == nil) {
        instance = [[HTTPHelper alloc] init];
    }
    
    return instance;
}

/**
 *  sha1加密
 *  @param input 要加密的字符串
 *  return 加密好的字符串
 */
- (NSString *) sha1:(NSString *)input
{
    
    NSData *data = [input dataUsingEncoding:NSUTF8StringEncoding];
    
    uint8_t digest[CC_SHA1_DIGEST_LENGTH];
    
    CC_SHA1(data.bytes, (unsigned int)data.length, digest);
    
    NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
    
    for(int i=0; i<CC_SHA1_DIGEST_LENGTH; i++) {
        [output appendFormat:@"%02x", digest[i]];
    }
    
    return output;
}

- (void)setHeader:(NSDictionary *)params useToken:(BOOL)useToken {
    
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    
    NSMutableArray *keyArr = [NSMutableArray array];
    for (NSString *key in params.keyEnumerator) {
        
        NSString *keyEncoding = [key stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet characterSetWithCharactersInString:@"=?,':#%^{}\"[]|/\\<> "].invertedSet];
        NSString *valueMd5 = [[NSString stringWithFormat:@"%@",params[key]] lm_md5];
        
        [keyArr addObject:keyEncoding];
        dict[keyEncoding] = valueMd5;
    }
    
    //排序
    [keyArr sortUsingComparator:^NSComparisonResult(NSString *key1, NSString *key2) {

        return [key1 compare:key2 options:NSLiteralSearch];
    }];
    
    //拼接字符串
    NSMutableString *authorization = [NSMutableString string];
    for (NSInteger i = 0; i < keyArr.count; i++) {
        NSString *key = keyArr[i];
        
        [authorization appendFormat:@"&%@=%@",key,dict[key]];
    }
    
    //加密
    NSString *orginSha1 = [[authorization substringFromIndex:1] stringByAppendingString:Access_Secter];
    NSString *sha1Auth = [self sha1:orginSha1];
    
    //设置请求头
    [self.requestSerializer setValue:Access_Key forHTTPHeaderField:@"Access-Key"];
    [self.requestSerializer setValue:sha1Auth forHTTPHeaderField:@"Authorizations"];
    //App-Version
    NSString *appVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
    [self.requestSerializer setValue:[@"ios/" stringByAppendingString:appVersion] forHTTPHeaderField:@"App-Version"];

    if (useToken) {
        
        [self.requestSerializer setValue:[UserDefaultsHelper getStringForKey:WM_TOKEN] forHTTPHeaderField:@"Access-Token"];
    }
    
    NSLog(@"%@",orginSha1);
    NSLog(@"%@",params);
    NSLog(@"%@",self.requestSerializer.HTTPRequestHeaders);
    
}

- (void(^)(NSURLSessionDataTask * , NSDictionary *, HTTPStatus *))
addWaitText:(NSString *)text
    success:(void(^)(NSURLSessionDataTask * , NSDictionary *, HTTPStatus *))success {
    
    return ^(NSURLSessionDataTask * task, NSDictionary *result, HTTPStatus *status){
        if (text.length) {
            [MBProgressHUD hideAll];
        }
        if (success) {
            success(task,result,status);
        }
    };
}

- (void(^)(NSURLSessionDataTask *, NSError *))
addWaitText:(NSString *)text
    failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure{
    
    return ^(NSURLSessionDataTask *task, NSError *error){
        if (text.length) {
            [MBProgressHUD hideAll];
        }
        
        if(failure){
            failure(task,error);
        }
    };
}

- (void(^)(NSURLSessionDataTask *, id))
formatSuccess:(void (^)(NSURLSessionDataTask *task, NSDictionary *result, HTTPStatus *status))success
{
    
    return ^(NSURLSessionDataTask *task, id response){
        
        if (success) {
            success(task,response[@"result"],[HTTPStatus mj_objectWithKeyValues:response[@"status"]]);
        }
    };
}

- (void (^)(NSURLSessionDataTask *, NSError *))
formatFailure:(void(^)(NSURLSessionDataTask *task, NSError *error))failure{
    
    return  ^(NSURLSessionDataTask *task, NSError *error){
        NSLog(@"请求失败------:  %@",error);
//        [MBProgressHUD showText:@"网络不给力" onView:nil];
        if (failure) {
            
            failure(task,error);
        }
    };
}

- (void)showText:(NSString *)text {
    if (text.length) {
        [MBProgressHUD showMessage:text];
    }
}

- (NSDictionary *)setHeader:(BOOL)useToken AddTimeWithDict:(NSDictionary *)dict {
    
    NSMutableDictionary *params = [NSMutableDictionary dictionaryWithDictionary:dict];
    params[@"_t"] = @([CommonTool getTimeStamp]);
    [self setHeader:params useToken:useToken];
    
    return params;
}


@end
